// Evol functions.
// Authors:
//    gumi
//    omatt
//    Travolta
// Description:
//    Fishing functions.
// Variable
//    .dir
//         DOWN    Never try or pulled too late
//         UP      Bait dropped
//         LEFT    Fish bite bait
//
// player log on .dir is DOWN, start by choose bait menu
// player chooses bait, script addtimer in npc .dir is UP
// if player pulls before signal npc, bait is lost, set .bait to DOWN goto choose bait
// if player pulls after pull delay max, bait is lost, set .bait to DOWN goto choose bait
// npc signal .dir is LEFT
// player pulls between npc signal and pulls delay max, got the fish, set .dir to DOWN goto choose bait

function	script	fishing_cleanup	{
    .@npc$ = getarg(0, "");
    if (.@npc$ == "") end;

    set getvariableofnpc(.char_id, .@npc$), 0; // clean acc id
    set getvariableofnpc(.account_id, .@npc$), 0; // clean char id
    set getvariableofnpc(.last_used, .@npc$), gettimetick(2); // set last used time
    setnpcdir .@npc$, DOWN; // reset direction
    return;
}

-	script	global fishing handler	32767,{
    end;

OnBite:
    if (getnpcdir(@fishing_spot$) != UP)
        end;

    setnpcdir @fishing_spot$, LEFT;
    @fishing_tick = gettimetick(0);
    misceffect getvariableofnpc(.bite_fx, @fishing_spot$);
    end;

OnCleanUp:
    dispbottom l("You waited too long and lost the bait...");
    specialeffect2 getvariableofnpc(.failure_fx, @fishing_spot$), SELF; // event fail
OnPCLogoutEvent:
    fishing_cleanup @fishing_spot$;
    @fishing_spot$ = ""; // unbind fishing npc
    end;
}

function	script	fishing	{

///////////////////////////////////////////
// Var initialization

    .@npc$ = strnpcinfo(0); // the full name of the fishing spot

    .@account_id = getvariableofnpc(.account_id, .@npc$); // the account id of the player using the fishing spot
    .@char_id = getvariableofnpc(.char_id, .@npc$); // the char id of the player using the fishing spot
    .@dir = getnpcdir(.@npc$); // direction of the fishing spot
    .@last_used = getvariableofnpc(.last_used, .@npc$); // when this fishing spot was last used
    .@baits = getvariableofnpc(.baits, .@npc$); // bait count

    .@rod = getvariableofnpc(.fishing_rod, .@npc$); // the fishing rod required for this spot
    .@rod = (.@rod ? .@rod : FishingRod);

    .@regen_time = getvariableofnpc(.cooldown, .@npc$); // cooldown for the fishing spot
    .@regen_time = (.@regen_time ? .@regen_time : 20);

    .@success_fx = getvariableofnpc(.success_fx, .@npc$); // effect to show on success
    .@success_fx = (.@success_fx ? .@success_fx : 27);

    .@failure_fx = getvariableofnpc(.failure_fx, .@npc$); // effect to show on failure
    if (.@failure_fx < 1)
    {
        .@failure_fx = 28;
        set getvariableofnpc(.failure_fx, .@npc$), .@failure_fx; // needed by global handler
    }

    .@initial_fx = getvariableofnpc(.initial_fx, .@npc$); // effect to show when throwing the bait
    .@initial_fx = (.@initial_fx ? .@initial_fx : 29);

    .@bite_fx = getvariableofnpc(.bite_fx, .@npc$); // effect to show when something bites
    if (.@bite_fx < 1)
    {
        .@bite_fx = 30;
        set getvariableofnpc(.bite_fx, .@npc$), .@bite_fx; // needed by global handler
    }

    .@wait_time_min = getvariableofnpc(.wait_time_min, .@npc$); // min amount of time to wait for the line to sink
    .@wait_time_min = (.@wait_time_min ? .@wait_time_min : 4000);

    .@wait_time_max = getvariableofnpc(.wait_time_max, .@npc$); // max amount of time to wait for the line to sink
    .@wait_time_max = (.@wait_time_max ? .@wait_time_max : 18000);

    .@catch_time = getvariableofnpc(.catch_time, .@npc$); // the player must catch the fish within X ms after the line sinks
    .@catch_time = (.@catch_time ? .@catch_time : 5000);

    .@pull_rand_max = getvariableofnpc(.pull_rand_max, .@npc$);
    .@pull_rand_max = (.@pull_rand_max ? .@pull_rand_max : 800);

    .@fish_id = getvariableofnpc(.common_fish, .@npc$);
    .@fish_id = (.@fish_id ? .@fish_id : CommonCarp);

    .@rare_id = getvariableofnpc(.rare_fish, .@npc$);
    .@rare_fish = (.@rare_fish ? .@rare_fish : GrassCarp);

    .@rare_fish_chance = getvariableofnpc(.rare_fish_chance, .@npc$);
    .@rare_fish_chance = (.@rare_fish_chance ? .@rare_fish_chance : 25);

    if (getvariableofnpc(.bait_ids[0], .@npc$) < 1)
    {
        // default baits (bait, chance booster)
        setarray getvariableofnpc(.bait_ids[0], .@npc$),
            SmallTentacles, 0,
            Bread, 0,
            Aquada, 1,
            UrchinMeat, 0,
            TortugaTongue, 2,
            Tentacles, 0;
    }

    if (.@baits < 1)
    {
        // only count it once
        .@baits = getarraysize(getvariableofnpc(.bait_ids[0], .@npc$));
        set getvariableofnpc(.baits, .@npc$), .@baits;
    }


///////////////////////////////////////////
// Logic below

    if (countitem(.@rod) < 1)
    {
        dispbottom l("You don't have any @@.", getitemlink(.@rod));
        return -1;
    }

    if (.@account_id > 0 && !isloggedin(.@account_id, .@char_id))
    {
        fishing_cleanup .@npc$; // reset
        .@dir = DOWN;
    }

    if (.@char_id != getcharid(CHAR_ID_CHAR) && .@dir != DOWN)
    {
        dispbottom l("This fishing spot is already being used!");
        return -2;
    }


    // pull too soon
    if (.@dir == UP)
    {
        deltimer "global fishing handler::OnCleanUp"; // cancel auto cleanup
        deltimer "global fishing handler::OnBite";
        specialeffect2 .@failure_fx, SELF;  // event fail
        fishing_cleanup .@npc$; // do it manually instead
        dispbottom l("You pulled too soon and lost the bait.");
        return -3;
    }

    // pull maybe on time
    else if (.@dir == LEFT)
    {
        deltimer "global fishing handler::OnCleanUp"; // cancel auto cleanup
        fishing_cleanup .@npc$; // do it manually instead

        getmapxy .@mapbis$, .@xbis, .@ybis, UNITTYPE_PC; // get current char location

        // Leave spot, lost the bait
        if (.@mapbis$ != @fishing_loc$[0] || .@xbis != @fishing_loc[0] || .@ybis != @fishing_loc[1] || @fishing_spot$ != .@npc$)
        {
            dispbottom l("You left your fishing spot!");
            return -4;
        }

        // RNG to obtain a rare fish
        // TODO: chance booster
        if (rand(.@rare_fish_chance) == 0)
        {
            // TODO: rare fish array
            .@fish_id = .@rare_id;
        }
        // TODO: else common fish array

        // RNG to obtain a fish
        if (rand(gettimetick(0) - @fishing_tick) <= .@pull_rand_max)
        {
            specialeffect2 .@success_fx, SELF; // event success

            if(!checkweight(.@fish_id, 1))
            {
                dispbottom l("You caught a @@ but had no room in your inventory to carry it.", getitemlink(.@fish_id));
                makeitem .@fish_id, 1, .@mapbis$, .@xbis, .@ybis; // drop on the ground
                return 0;
            }

            //dispbottom l("You caught a @@!", getitemlink(.@fish_id)); <= already shows "you picked up [...]"
            getitem .@fish_id, 1;
        }
        else
        {
            dispbottom l("You pulled too late and lost the bait...");
            specialeffect2 .@failure_fx, SELF;  // event fail
            .@fish_id = 0;
        }

        return .@fish_id;
    }



    if (gettimetick(2) - .@last_used < .@regen_time)
    {
        dispbottom l("This fishing spot has just been used, give it a rest.");
        return -5;
    }


    // begin fishing
    narrator 4,
        l("You see some fish reflecting the sun on the surface of the water."),
        l("What will be the bait for the fish?");

    mes "##B" + l("Drag and drop an item from your inventory.") + "##b";

    .@bait = requestitem();
    .@bait_c = false;

    if (.@bait < 1)
    {
        narrator 1,
            l("You take your fishing rod and leave.");

        return -6;
    }

    if (countitem(.@bait) < 1)
    {
        return -6;
    }

    for (.@i = 0; .@i < .@baits; .@i += 2)
    {
        if (getvariableofnpc(.bait_ids[.@i], .@npc$) == .@bait)
        {
            .@bait_c = true;
            break;
        }
    }

    if (.@bait_c != true)
    {
        narrator 1,
            l("This item cannot be used as bait here.");

        return -6;
    }

    if (getvariableofnpc(.char_id, .@npc$) > 0)
    {
        narrator 1,
            l("Somebody took your place on this spot!"),
            l("You take your fishing rod and leave.");
        return -8;
    }

    @fishing_spot$ = .@npc$; // bind player to fishing spot
    set getvariableofnpc(.account_id, .@npc$), getcharid(CHAR_ID_ACCOUNT); // record account id
    set getvariableofnpc(.char_id, .@npc$), getcharid(CHAR_ID_CHAR); // record char id
    set getvariableofnpc(.last_used, .@npc$), gettimetick(2);
    getmapxy (@fishing_loc$[0], @fishing_loc[0], @fishing_loc[1], 0); // record char pos
    delitem .@bait, 1;

    // The player uses this spot, his bait is ready, he just has to wait for the signal.
    closedialog;

    misceffect .@initial_fx; // throw the bait
    sleep2 800;    // wait 0.8s for synchronize the sound of "plop" in water with the npc dir UP.
    setnpcdir .@npc$, UP;

    dispbottom l("Wait for the bait to sink underwater.");

    .@delay = rand(.@wait_time_min, .@wait_time_max);

    addtimer .@delay, "global fishing handler::OnBite"; // bite logic
    addtimer (.@delay + .@catch_time), "global fishing handler::OnCleanUp"; // auto clean up

    return 0;
}
